package com.kexio.user.service.impl;

import java.util.List;
import java.util.concurrent.CompletableFuture;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.kexio.auth.cache.CacheInvalidationService;
import com.kexio.user.service.PermissionSyncService;

import cn.dev33.satoken.stp.StpUtil;

/**
 * 权限同步服务实现
 * 
 * 🎯 设计思路：
 * 1. 权限变更时立即清理相关缓存
 * 2. 通过Sa-Token刷新在线用户的权限信息
 * 3. 异步处理批量权限同步，避免阻塞主线程
 * 4. 支持多租户权限隔离
 * 
 * 🚀 性能优化：
 * - 只同步在线用户的权限
 * - 批量操作使用异步处理
 * - 缓存清理和权限刷新分离
 * 
 * @author Kexio Team
 * @since 2.2.0
 */
@Service
public class PermissionSyncServiceImpl implements PermissionSyncService {
    
    private static final Logger logger = LoggerFactory.getLogger(PermissionSyncServiceImpl.class);
    
    @Autowired
    private CacheInvalidationService cacheInvalidationService;
    
    @Override
    public void syncUserPermissions(String userId, String tenantId, String changeReason) {
        if (userId == null || tenantId == null) {
            logger.warn("用户ID或租户ID为空，跳过权限同步: userId={}, tenantId={}", userId, tenantId);
            return;
        }
        
        try {
            logger.info("🔄 开始同步用户权限: userId={}, tenantId={}, reason={}", userId, tenantId, changeReason);
            
            // 1. 检查用户是否在线
            if (!shouldSyncUser(userId, tenantId)) {
                logger.debug("用户不在线或不需要同步，跳过: userId={}", userId);
                return;
            }
            
            // 2. 清理用户相关权限缓存
            cacheInvalidationService.clearUserCaches(userId, tenantId);
            
            // 3. 强制Sa-Token重新获取用户权限
            String complexLoginId = buildComplexLoginId(userId, tenantId);
            if (StpUtil.isLogin(complexLoginId)) {
                // 强制退出用户，下次访问时自动重新加载权限
                StpUtil.logout(complexLoginId);
                logger.info("✅ 用户权限同步完成（已强制刷新会话）: userId={}, tenantId={}", userId, tenantId);
            }
            
        } catch (Exception e) {
            logger.error("❌ 同步用户权限失败: userId={}, tenantId={}, reason={}", userId, tenantId, changeReason, e);
        }
    }
    
    @Override
    public void syncRolePermissions(String roleId, String tenantId, String changeReason) {
        if (roleId == null || tenantId == null) {
            logger.warn("角色ID或租户ID为空，跳过权限同步: roleId={}, tenantId={}", roleId, tenantId);
            return;
        }
        
        try {
            logger.info("🔄 开始同步角色权限: roleId={}, tenantId={}, reason={}", roleId, tenantId, changeReason);
            
            // 1. 清理角色相关权限缓存
            cacheInvalidationService.clearRoleCaches(roleId, tenantId);
            
            // 2. 异步获取拥有该角色的用户并同步权限
            CompletableFuture.runAsync(() -> {
                try {
                    // 简化方案：直接清理角色相关的所有权限缓存
                    cacheInvalidationService.clearAllPermissionRelatedCaches(tenantId);
                    logger.info("✅ 角色权限同步完成: roleId={}", roleId);
                    
                } catch (Exception e) {
                    logger.error("❌ 异步同步角色权限失败: roleId={}, tenantId={}", roleId, tenantId, e);
                }
            });
            
        } catch (Exception e) {
            logger.error("❌ 同步角色权限失败: roleId={}, tenantId={}, reason={}", roleId, tenantId, changeReason, e);
        }
    }
    
    @Override
    public void syncMenuPermissions(String menuId, String tenantId, String changeReason) {
        if (menuId == null || tenantId == null) {
            logger.warn("菜单ID或租户ID为空，跳过权限同步: menuId={}, tenantId={}", menuId, tenantId);
            return;
        }
        
        try {
            logger.info("🔄 开始同步菜单权限: menuId={}, tenantId={}, reason={}", menuId, tenantId, changeReason);
            
            // 1. 清理菜单相关权限缓存
            cacheInvalidationService.clearMenuCaches(menuId, tenantId);
            
            // 2. 菜单权限变更通常影响面较大，清理整个租户的权限缓存
            cacheInvalidationService.clearAllPermissionRelatedCaches(tenantId);
            
            logger.info("✅ 菜单权限同步完成: menuId={}, tenantId={}", menuId, tenantId);
            
        } catch (Exception e) {
            logger.error("❌ 同步菜单权限失败: menuId={}, tenantId={}, reason={}", menuId, tenantId, changeReason, e);
        }
    }
    
    @Override
    public void batchSyncUserPermissions(List<String> userIds, String tenantId, String changeReason) {
        if (userIds == null || userIds.isEmpty() || tenantId == null) {
            logger.warn("用户ID列表为空或租户ID为空，跳过批量权限同步: userCount={}, tenantId={}", 
                       userIds != null ? userIds.size() : 0, tenantId);
            return;
        }
        
        logger.info("🔄 开始批量同步用户权限: userCount={}, tenantId={}, reason={}", userIds.size(), tenantId, changeReason);
        
        // 异步批量处理，避免阻塞主线程
        CompletableFuture.runAsync(() -> {
            int successCount = 0;
            int failureCount = 0;
            
            for (String userId : userIds) {
                try {
                    syncUserPermissions(userId, tenantId, changeReason);
                    successCount++;
                } catch (Exception e) {
                    failureCount++;
                    logger.warn("批量同步中单个用户权限失败: userId={}, error={}", userId, e.getMessage());
                }
            }
            
            logger.info("✅ 批量用户权限同步完成: 成功={}, 失败={}, 总数={}", successCount, failureCount, userIds.size());
        });
    }
    
    @Override
    public void syncAllTenantPermissions(String tenantId, String changeReason) {
        if (tenantId == null) {
            logger.warn("租户ID为空，跳过租户权限同步");
            return;
        }
        
        logger.warn("🔄 开始同步租户所有用户权限: tenantId={}, reason={}", tenantId, changeReason);
        
        try {
            // 1. 清理租户所有权限相关缓存
            cacheInvalidationService.clearAllPermissionRelatedCaches(tenantId);
            
            // 2. 使用缓存清理服务刷新权限缓存
            cacheInvalidationService.clearAllPermissionRelatedCaches(tenantId);
            
            logger.warn("✅ 租户权限同步完成: tenantId={}", tenantId);
            
        } catch (Exception e) {
            logger.error("❌ 同步租户权限失败: tenantId={}, reason={}", tenantId, changeReason, e);
        }
    }
    
    @Override
    public boolean shouldSyncUser(String userId, String tenantId) {
        if (userId == null || tenantId == null) {
            return false;
        }
        
        try {
            // 检查用户是否在线（使用复合loginId）
            String complexLoginId = buildComplexLoginId(userId, tenantId);
            return StpUtil.isLogin(complexLoginId);
            
        } catch (Exception e) {
            logger.debug("检查用户在线状态失败: userId={}, tenantId={}, error={}", userId, tenantId, e.getMessage());
            return false;
        }
    }
    
    /**
     * 构建复合LoginId（支持多租户权限缓存隔离）
     */
    private String buildComplexLoginId(String userId, String tenantId) {
        if (tenantId == null || "null".equals(tenantId)) {
            return userId; // 单租户模式
        }
        return tenantId + ":" + userId; // 多租户模式
    }
}
